package ss.pku.jsa.worklist.om;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import ss.pku.jsa.worklist.sethelper.SetExcludeHelper;
import ss.pku.jsa.worklist.sethelper.SetIntersectionHelper;
import ss.pku.jsa.worklist.sethelper.SetUnionHelper;

public class Expression<M, K> implements Element<M, K> {

	private List<Element<M, K>> exp;
	private ExpressionOperator op;

	public Expression(Element<M, K> initEle, ExpressionOperator op) {
		this.exp = new ArrayList<Element<M, K>>();
		this.op = op;
		this.exp.add(initEle);
	}
	
	public boolean containsElement(Variable<M,K> var){
		for(Element<M, K> ele : exp){
			if(ele.getClass().equals(var.getClass())){
				if(ele.equals(var))
					return true;
			}
			else if(ele.getClass().equals(this.getClass())){
				if(((Expression<M, K>)ele).containsElement(var)){
					return true;
				}
			}
		}
		return false;
	}

	public Set<Value<M, K>> evaluate() {
		Set<Value<M, K>> result = null;
		switch (this.op) {
		case Union:
			for(Element<M, K> ele : exp)
			{
				if(result == null)
				{
					result = ele.evaluate();
				}
				else
				{
					result = 
						SetUnionHelper.execute(result, ele.evaluate());
				}
			}
			break;
		case Intersection:
			for(Element<M, K> ele : exp)
			{
				if(result == null)
				{
					result = ele.evaluate();
				}
				else
				{
					result = 
						SetIntersectionHelper.execute(result, ele.evaluate());
				}
			}
			break;
		case Exclude:
			for(Element<M, K> ele : exp)
			{
				if(result == null)
				{
					result = ele.evaluate();
				}
				else
				{
					result = 
						SetExcludeHelper.execute(result, ele.evaluate());
				}
			}
			break;
		default:
			throw new UnsupportedOperationException();
		}
		
		return result;
	}

	public void addElement(Element<M, K> ele) {
		this.exp.add(ele);
	}

	public enum ExpressionOperator {
		Union, Intersection, Exclude
	}

}